﻿using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;
using SharedClassLibrary;
using System.Security.Claims;

namespace BlazorWebAssemblyDemo.Authentication
{
    public class JwtAuthenticationStateProvider : AuthenticationStateProvider
    {
        //常量
        private const string key = "authToken";
        private const string authenticationType = "jwt";

        /// <summary>
        /// 本地存储
        /// </summary>
        private readonly ILocalStorageService localStorage;

        /// <summary>
        /// HttpClient
        /// </summary>
        private readonly HttpClient httpClient;

        /// <summary>
        /// 认证状态
        /// </summary>
        private AuthenticationState anonymous;

        /// <summary>
        /// 本地token
        /// </summary>
        public string TokenInLocalStorage { get; private set; }

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="localStorage"></param>
        /// <param name="httpClient"></param>
        public JwtAuthenticationStateProvider(ILocalStorageService localStorage, HttpClient httpClient)
        {
            this.anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            this.localStorage = localStorage;
            this.httpClient = httpClient;
        }

        /// <summary>
        /// 获取认证状态
        /// </summary>
        /// <returns></returns>
        public override async Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            //确认localstorage里面是否有token
            TokenInLocalStorage = await localStorage.GetItemAsStringAsync(key);
            if (string.IsNullOrEmpty(TokenInLocalStorage))
            {
                //沒有的話，回传匿名使用者
                return anonymous;
            }
            var session = Generics.GetClaimsFromToken(TokenInLocalStorage);
            var claims = Generics.SetClaimsPrincipal(session);

            //在每次request的header中带入bearer token
            httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", TokenInLocalStorage);

            //回传带有user claim的AuthenticationState物件
            return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType)));
        }

        /// <summary>
        /// 登录后 通知状态改变
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task NotifyUserAuthentication(string token)
        {
            var session = Generics.GetClaimsFromToken(token);
            var claims = Generics.SetClaimsPrincipal(session);
            var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType));
            await localStorage.SetItemAsStringAsync(key, token);
            var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
            NotifyAuthenticationStateChanged(authState);
        }

        /// <summary>
        /// 注销后 通知状态改变
        /// </summary>
        public async Task NotifyUserLogOut()
        {
            await localStorage.RemoveItemAsync(key);
            var authState = Task.FromResult(anonymous);
            NotifyAuthenticationStateChanged(authState);
        }
    }
}
